package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type API struct {
	state   *State
	cfgPath string
	proxy   *Proxy
}

func NewAPI(state *State, cfgPath string, proxy *Proxy) *API {
	return &API{state: state, cfgPath: cfgPath, proxy: proxy}
}

func (a *API) Router() http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/routes", a.handleRoutes)
	mux.HandleFunc("/routes/", a.handleRouteOne)
	mux.HandleFunc("/certs", a.handleCert)
	mux.HandleFunc("/certs/upload", a.handleCertUpload)
	mux.HandleFunc("/sites", a.handleSites) // 新增：添加站点（可同时上传证书）
	return mux
}

// GET /routes -> list, PUT /routes -> upsert {domain, target}
func (a *API) handleRoutes(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		fc := a.state.Snapshot()
		writeJSON(w, http.StatusOK, fc)
	case http.MethodPut:
		var body struct {
			Domain    string           `json:"domain"`
			Target    string           `json:"target,omitempty"` // 兼容旧格式
			Servers   []UpstreamServer `json:"servers,omitempty"`
			Algorithm string           `json:"algorithm,omitempty"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		if body.Domain == "" {
			http.Error(w, "domain required", http.StatusBadRequest)
			return
		}
		up := Upstream{}
		if len(body.Servers) > 0 {
			up.Servers = body.Servers
			up.Algorithm = body.Algorithm
		} else if body.Target != "" {
			// 兼容旧格式
			up.Target = body.Target
		} else {
			http.Error(w, "target or servers required", http.StatusBadRequest)
			return
		}
		a.state.SetRoute(body.Domain, up)
		// 使负载均衡器失效，强制重新创建
		a.proxy.invalidateBalancer(body.Domain)
		if err := persistFileConfig(a.cfgPath, toFileConfig(a.state)); err != nil {
			log.Printf("save config failed: %v", err)
		}
		writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
	default:
		http.NotFound(w, r)
	}
}

// DELETE /routes/{domain}
func (a *API) handleRouteOne(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodDelete {
		http.NotFound(w, r)
		return
	}
	parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/routes/"), "/")
	if len(parts) == 0 || parts[0] == "" {
		http.Error(w, "domain required", http.StatusBadRequest)
		return
	}
	domain := parts[0]
	a.state.DeleteRoute(domain)
	// 清除负载均衡器缓存
	a.proxy.invalidateBalancer(domain)
	if err := persistFileConfig(a.cfgPath, toFileConfig(a.state)); err != nil {
		log.Printf("save config failed: %v", err)
	}
	writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

// PUT /certs {domain, cert_file, key_file}
func (a *API) handleCert(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		http.NotFound(w, r)
		return
	}
	var body struct {
		Domain   string `json:"domain"`
		CertFile string `json:"cert_file"`
		KeyFile  string `json:"key_file"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	if body.Domain == "" || body.CertFile == "" || body.KeyFile == "" {
		http.Error(w, "domain, cert_file, key_file required", http.StatusBadRequest)
		return
	}
	a.state.SetCertPath(body.Domain, body.CertFile, body.KeyFile)
	if err := persistFileConfig(a.cfgPath, toFileConfig(a.state)); err != nil {
		log.Printf("save config failed: %v", err)
	}
	writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

func writeJSON(w http.ResponseWriter, code int, v any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	_ = json.NewEncoder(w).Encode(v)
}

func toFileConfig(s *State) *FileConfig {
	snap := s.Snapshot()
	return &snap
}

// POST /sites - 添加站点（可同时上传证书文件）
func (a *API) handleSites(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.NotFound(w, r)
		return
	}

	// 解析 multipart/form-data
	if err := r.ParseMultipartForm(32 << 20); err != nil { // 32MB max
		http.Error(w, fmt.Sprintf("parse form: %v", err), http.StatusBadRequest)
		return
	}

	domain := r.FormValue("domain")
	target := r.FormValue("target")
	if domain == "" || target == "" {
		http.Error(w, "domain and target required", http.StatusBadRequest)
		return
	}

	// 设置路由（兼容旧格式，单服务器）
	a.state.SetRoute(domain, Upstream{
		Servers:   []UpstreamServer{{Target: target, Weight: 1}},
		Algorithm: "round-robin",
	})
	// 使负载均衡器失效
	a.proxy.invalidateBalancer(domain)

	// 处理证书文件上传（可选）
	certFile, certHeader, err := r.FormFile("cert_file")
	keyFile, keyHeader, err2 := r.FormFile("key_file")

	if err == nil && err2 == nil && certFile != nil && keyFile != nil {
		// 确保 certs 目录存在
		certsDir := "certs"
		if err := os.MkdirAll(certsDir, 0755); err != nil {
			log.Printf("create certs dir failed: %v", err)
		} else {
			// 保存证书文件
			certPath := filepath.Join(certsDir, fmt.Sprintf("%s.crt", domain))
			keyPath := filepath.Join(certsDir, fmt.Sprintf("%s.key", domain))

			if err := saveUploadedFile(certFile, certPath); err != nil {
				log.Printf("save cert file failed: %v", err)
				http.Error(w, fmt.Sprintf("save cert: %v", err), http.StatusInternalServerError)
				return
			}
			certFile.Close()

			if err := saveUploadedFile(keyFile, keyPath); err != nil {
				log.Printf("save key file failed: %v", err)
				os.Remove(certPath) // 清理已保存的证书
				http.Error(w, fmt.Sprintf("save key: %v", err), http.StatusInternalServerError)
				return
			}
			keyFile.Close()

			// 更新证书路径
			a.state.SetCertPath(domain, certPath, keyPath)
			log.Printf("uploaded cert for %s: %s, %s", domain, certHeader.Filename, keyHeader.Filename)
		}
	} else if certFile != nil {
		certFile.Close()
	}
	if keyFile != nil {
		keyFile.Close()
	}

	// 持久化配置
	if err := persistFileConfig(a.cfgPath, toFileConfig(a.state)); err != nil {
		log.Printf("save config failed: %v", err)
	}

	writeJSON(w, http.StatusOK, map[string]string{
		"status": "ok",
		"domain": domain,
		"target": target,
	})
}

// POST /certs/upload - 上传证书文件
func (a *API) handleCertUpload(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.NotFound(w, r)
		return
	}

	if err := r.ParseMultipartForm(32 << 20); err != nil {
		http.Error(w, fmt.Sprintf("parse form: %v", err), http.StatusBadRequest)
		return
	}

	domain := r.FormValue("domain")
	if domain == "" {
		http.Error(w, "domain required", http.StatusBadRequest)
		return
	}

	certFile, certHeader, err := r.FormFile("cert_file")
	if err != nil {
		http.Error(w, fmt.Sprintf("cert_file required: %v", err), http.StatusBadRequest)
		return
	}
	defer certFile.Close()

	keyFile, keyHeader, err2 := r.FormFile("key_file")
	if err2 != nil {
		http.Error(w, fmt.Sprintf("key_file required: %v", err2), http.StatusBadRequest)
		return
	}
	defer keyFile.Close()

	// 确保 certs 目录存在
	certsDir := "certs"
	if err := os.MkdirAll(certsDir, 0755); err != nil {
		http.Error(w, fmt.Sprintf("create certs dir: %v", err), http.StatusInternalServerError)
		return
	}

	// 保存文件
	certPath := filepath.Join(certsDir, fmt.Sprintf("%s.crt", domain))
	keyPath := filepath.Join(certsDir, fmt.Sprintf("%s.key", domain))

	if err := saveUploadedFile(certFile, certPath); err != nil {
		http.Error(w, fmt.Sprintf("save cert: %v", err), http.StatusInternalServerError)
		return
	}

	if err := saveUploadedFile(keyFile, keyPath); err != nil {
		os.Remove(certPath) // 清理已保存的证书
		http.Error(w, fmt.Sprintf("save key: %v", err), http.StatusInternalServerError)
		return
	}

	// 更新配置
	a.state.SetCertPath(domain, certPath, keyPath)
	if err := persistFileConfig(a.cfgPath, toFileConfig(a.state)); err != nil {
		log.Printf("save config failed: %v", err)
	}

	writeJSON(w, http.StatusOK, map[string]string{
		"status":    "ok",
		"domain":    domain,
		"cert_file": certPath,
		"key_file":  keyPath,
		"uploaded":  fmt.Sprintf("%s, %s", certHeader.Filename, keyHeader.Filename),
	})
}

func saveUploadedFile(src io.Reader, dstPath string) error {
	dst, err := os.Create(dstPath)
	if err != nil {
		return err
	}
	defer dst.Close()

	if _, err := io.Copy(dst, src); err != nil {
		os.Remove(dstPath)
		return err
	}
	return nil
}
